/**
 * @file gestiondesmessages.c
 * @author Florian Castellane <florian.castellane@grenoble-inp.org>
 * @author Christian Proust <christian.proust@phelma.grenoble-inp.fr>
 * @date Tue Sep 25 23:26:00 2012
 * @brief Fonctions de gestion des messages.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> // fonctions à nombre variable d'arguments
#include <time.h>
#include "include/gestiondesmessages.h"

// Fichier de journalisation
typedef FILE *FICHIER_JOURNAL;
static FICHIER_JOURNAL Fichier_journal = NULL;

// Dernière erreur renvoyée par le programme
static CODEERREUR ERREURENCOURS = ERREUR_PASDERREUR;    // a l'initialisation, pas d'erreur (avec un peu de chance, ça viendra !)

// Niveau d'erreur minimal affiché pour tout le programme
static NIVEAUERREUR NIVEAU_DE_VERBOSITE = NIVEAU_NOTE;  // par défaut on affiche les erreurs, avertissements et notes

/**
 *
 * @return date d'exécution de la fonction
 * @brief pointeur de structure renvoyant la date
 *
 */

static struct tm* date(void)
{
    time_t date = time(NULL);
    return localtime(&date);
}

/**
 *
 * @brief fonction écrivant le niveau d'erreur dans le journal
 *
 */

static void ecritniveauerreur(NIVEAUERREUR niveau)
{
    if (!Fichier_journal) return;   // ne rien faire si le fichier journal n'est pas ouvert
    if (niveau <= NIVEAU_ERROR)
    {
        static const char *tab[] =
        {
            "[DEBUG    ]",
            "[INFO     ]",
            "[ATTENTION]",
            "[ERREUR   ]"
        };
        fprintf(Fichier_journal,"%s\t",tab[niveau]);
    }

}

/**
 *
 * @brief fonction écrivant l'heure dans le journal
 *
 */

static void ecritdate(void)
{
    if(!Fichier_journal) return;    // ne rien faire si le fichier journal n'est pas ouvert
    else
    {
        struct tm *t=date();
        fprintf(Fichier_journal,"%dh%d:m%ds : \t", t->tm_hour, t->tm_min, t->tm_sec);
    }
}

/**
 *
 * @brief traduit un code d'erreur
 * @param codeerreur un code d'erreur de type CODEERREUR
 * @return une chaîne contenant le nom de l'erreur en français
 *
 */

// traduit le type d'erreur
char* gestiondesmessages_traduiterreur(CODEERREUR codeerreur)   // remplace strerror
{
    static const char *tab[] =
    {
        "Aucune erreur",
        "Erreur d\'allocation",
        "Erreur d\'ouverture de fichier",
        "Erreur de fermeture de fichier",
        "Erreur de parametre"
        // aucune chaîne pour le dernier élément
    };
    return codeerreur<NOMBRE_CODES_ERREUR ? (char *)tab[codeerreur]:NULL;   // renvoyer une chaîne vide en cas de code invalide
}

/**
 *
 * @brief affiche l'erreur détaillée
 * @param message un message d'erreur relatif à la fonction
 *
 */

void gestiondesmessages_afficheerreur(const char* message)
{
    if(message) // si c'est NULL (pas de message, erreur...) on ne fait rien
    {
        gestiondesmessages_ecritmessage(NIVEAU_ERROR,"%s: %s", message, gestiondesmessages_traduiterreur(ERREURENCOURS));
    }
}



void gestiondesmessages_ecritdebutligne(NIVEAUERREUR niveau)
{
    if (!Fichier_journal) return;   // ne rien faire si le fichier journal n'est pas ouvert
    else if (niveau >= NIVEAU_DE_VERBOSITE) // n'afficher que les messages du niveau demandé ou plus important
    {
        ecritniveauerreur(niveau);
        ecritdate();
    }
}

void gestiondesmessages_ecriretexte(NIVEAUERREUR niveau, const char* texte, ...)   // fonctions a nombre d'arguments variable
{
    if (!Fichier_journal) return;
    else if (niveau >= NIVEAU_DE_VERBOSITE)
    {
        va_list liste_variable_arguments;   // initialisation de la liste d'arguments
        va_start(liste_variable_arguments, texte);  // appel de la macro de liste variable d'arguments
        vfprintf(Fichier_journal, texte, liste_variable_arguments); // printf a nombre d'arguments variable
    }
}


/**
 *
 * @param nomdefichier nom du fichier de journalisation dans lequel écrire
 * @return 0 en cas de succès
 * @brief initialisation de la gestion des messages
 *
 */

int gestiondesmessages_initialisation(const char* nomdefichier)
{
    int retour=0;
    if(nomdefichier)
    {
        Fichier_journal = fopen(nomdefichier, "a");
        if (Fichier_journal == NULL)
        {
            perror("Erreur d\'ouverture du fichier de journalisation. Rien ne sera ecrit dans ce dernier.");
        }
    }
    return retour;
}

/**
 *
 * @return le pointeur de flot vers le fichier de journalisation
 * @brief fermeture de la gestion des messages
 *
 */

int gestiondesmessages_fermer(void)
{
    int i=fclose(Fichier_journal);  // si le fichier s'est bien fermé, fclose retourne 0
    if (!i) perror("Erreur de fermeture du fichier de journalisation");
    return i;
}
